/*
 * @lc app=leetcode.cn id=994 lang=cpp
 *
 * [994] 腐烂的橘子
 *
 * https://leetcode.cn/problems/rotting-oranges/description/
 *
 * algorithms
 * Medium (51.08%)
 * Likes:    594
 * Dislikes: 0
 * Total Accepted:    93.4K
 * Total Submissions: 182.9K
 * Testcase Example:  '[[2,1,1],[1,1,0],[0,1,1]]'
 *
 * 在给定的 m x n 网格 grid 中，每个单元格可以有以下三个值之一：
 * 
 * 
 * 值 0 代表空单元格；
 * 值 1 代表新鲜橘子；
 * 值 2 代表腐烂的橘子。
 * 
 * 
 * 每分钟，腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。
 * 
 * 返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能，返回 -1 。
 * 
 * 
 * 
 * 示例 1：
 * 
 * 
 * 
 * 
 * 输入：grid = [[2,1,1],[1,1,0],[0,1,1]]
 * 输出：4
 * 
 * 
 * 示例 2：
 * 
 * 
 * 输入：grid = [[2,1,1],[0,1,1],[1,0,1]]
 * 输出：-1
 * 解释：左下角的橘子（第 2 行， 第 0 列）永远不会腐烂，因为腐烂只会发生在 4 个正向上。
 * 
 * 
 * 示例 3：
 * 
 * 
 * 输入：grid = [[0,2]]
 * 输出：0
 * 解释：因为 0 分钟时已经没有新鲜橘子了，所以答案就是 0 。
 * 
 * 
 * 
 * 
 * 提示：
 * 
 * 
 * m == grid.length
 * n == grid[i].length
 * 1 <= m, n <= 10
 * grid[i][j] 仅为 0、1 或 2
 * 
 * 
 */

// @lc code=start
class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
        queue<pair<int, int>> que;
        memset(_dis, -1, sizeof(_dis));
        _cnt = 0;
        int n = grid.size();
        int m = grid[0].size();
        int res = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (grid[i][j] == 2) {
                    que.emplace(i, j);
                    _dis[i][j] = 0;
                } else if (grid[i][j] == 1) {
                    ++_cnt;
                }
            }
        }

        while (!que.empty()) {
            auto [x, y] = que.front();
            que.pop();
            for (int i = 0; i < 4; ++i) {
                int newX = x + dirX[i];
                int newY = y + dirY[i];
                if (newX < 0 || newX >= n || newY < 0 || newY >= m || ~_dis[newX][newY] || !grid[newX][newY]) {
                    continue;
                }
                _dis[newX][newY] = _dis[x][y] + 1;
                que.emplace(newX, newY);
                if (grid[newX][newY] == 1) {
                    --_cnt;
                    res = _dis[newX][newY];
                    if (!_cnt) {
                        break;
                    }
                }
            }
        }

        return _cnt ? -1 : res;
    }
private:
    int _cnt;
    int _dis[10][10];
    const int dirX[4] = {0, 1, 0, -1};
    const int dirY[4] = {1, 0, -1, 0};
};
// @lc code=end

